package actions.runnable;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Random;

import actions.JobTimer;

import objects.MessageCodes;
import objects.data.Message;
import objects.data.WorkPacket;


import ssh.SSHUtils;
import utils.PbsUtils;
import utils.Utils;
import utils.ZipUtils;

public class SubmitJob implements Runnable, MessageCodes {
	WorkPacket workPacket;

	public SubmitJob(WorkPacket wp) {
		this.workPacket = wp;
	}

	public void run() {
		Process child;
		try {
			JobTimer timerJob = new JobTimer(workPacket.uniqueId, workPacket.nodes, workPacket.ppn,
					Utils.ConvertWalltime(workPacket.walltime));
			String filename = new File(workPacket.sourceDir).getName();
			String path = workPacket.uniqueId + File.separator + filename;
			Runtime run = Runtime.getRuntime();
			Utils.out("+ creating dir " + workPacket.uniqueId);
			new File(workPacket.uniqueId).mkdir();
			Utils.out("+ downloading file " + path);

			if (!SSHUtils.ScpFrom(path)) {
				Utils.out("FAILED RETREIVNG FILE " + filename);
				Utils.ws.send(new Message(JOB_FAILED, workPacket.uniqueId));
				return;
			}
			
			if (filename.endsWith(".zip")) {
				ZipUtils.unzip(workPacket.uniqueId,path);
				new File(path).delete();
			}
			
			Utils.out("+ creating PBS file");
			child = run.exec("chmod 700 ./" + path);
			child.waitFor();

			PbsUtils.createPBSfile(workPacket);
			Utils.out("+ submitting job");
			if(!Utils.MOCK) {
				child = run.exec("qsub ./" + workPacket.uniqueId + File.separator + "PBS" + workPacket.jobname);
				timerJob.start();
				child.waitFor();
				Utils.out("+ starting job monitor thread");
				Utils.exec.execute(new JobMonitor(workPacket, timerJob));
			} else {
				Random rand = new Random();
				int queuetime = rand.nextInt(120);
				int runtime = Utils.ConvertWalltime(workPacket.walltime);
				Utils.out("+ mocking job: queuetime ["+queuetime+"s] runtime ["+runtime+"s]");
				Utils.ws.send(new Message(JOB_QUEUED, workPacket.uniqueId));
				//Thread.sleep(queuetime * 1000);
				Utils.ws.send(new Message(JOB_EXECUTING, workPacket.uniqueId));
				//Thread.sleep(runtime * 1000);
				FileWriter fstream = new FileWriter(workPacket.uniqueId + "/mockout.out",true);
				BufferedWriter out = new BufferedWriter(fstream);
				out.write(new Date().toGMTString()+": MOCK JOB QTIME["+queuetime+"s] RUNTIME["+runtime+"s]");
				out.close();
				Utils.out("+ job terminated: " + workPacket.jobname);
				Utils.out("+ zipping file " + workPacket.jobname);
				String outfile = workPacket.jobname + "_results.zip";
				
				ZipUtils.zip(workPacket.uniqueId, outfile);
				
				Utils.out("+ sftp: uploading file" + outfile);
				
				if (!SSHUtils.ScpTo(new File(outfile).getPath(), "~/" + workPacket.uniqueId
						+ "/" + outfile)) {
					Utils.out("FAILED SENDING FILE " + workPacket.uniqueId);
					Utils.ws.send(new Message(JOB_FAILED, workPacket.uniqueId));
					return;
				}
				
				Utils.out("+ cleaning up...");
				
				new File(outfile).delete();
				Utils.removeDirectory(new File(workPacket.uniqueId));
				Utils.ws.send(new Message(JOB_TERMINATED, workPacket.uniqueId));
			}
			

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
